package com.home.security.app.token;

import com.home.base.core.constants.UserInfoConstant;
import com.home.security.app.utils.StringHelper;
import io.jsonwebtoken.*;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Description: token 加密/解密
 * Created by 王大宸 on 2020-12-11 11:46
 * Created with IntelliJ IDEA.
 */
@Service
public class JWTHelper {

    /***
     * 功能说明：密钥加密token
     *
     * @author 王大宸
     * @date 2020/7/8 9:47
     * @param jwtInfo
     * @param priKey
     * @param expire
     * @return java.lang.String
     */
    public String generateToken(IJWTInfo jwtInfo, byte[] priKey, int expire) throws Exception {
        return Jwts.builder()
                .setSubject(jwtInfo.getUniqueName())
                .claim(UserInfoConstant.USER_ID, jwtInfo.getId())
                .claim(UserInfoConstant.USER_NAME, jwtInfo.getName())
                .claim(UserInfoConstant.EXPIRE, DateTime.now().plusSeconds(expire).toDate().getTime())
                .signWith(SignatureAlgorithm.RS256, RsaKeyHelper.getPrivateKey(priKey))
                .compact();
    }

    /***
     * 功能说明：密钥加密token
     *
     * @author 王大宸
     * @date 2020/7/8 9:47
     * @param jwtInfo
     * @param priKey
     * @param expire
     * @return java.lang.String
     */
    public String generateToken(IJWTInfo jwtInfo, byte[] priKey, Date expire) throws Exception {
        return Jwts.builder()
                .setSubject(jwtInfo.getUniqueName())
                .claim(UserInfoConstant.USER_ID, jwtInfo.getId())
                .claim(UserInfoConstant.USER_NAME, jwtInfo.getName())
                .claim(UserInfoConstant.EXPIRE, expire.getTime())
                .signWith(SignatureAlgorithm.RS256, RsaKeyHelper.getPrivateKey(priKey))
                .compact();
    }

    /***
     * 功能说明：密钥加密token
     *
     * @author 王大宸
     * @date 2020/7/8 9:46
     * @param jwtInfo
     * @param priKey
     * @param expire
     * @param otherInfo
     * @return java.lang.String
     */
    public String generateToken(IJWTInfo jwtInfo, byte[] priKey, Date expire, Map<String, String> otherInfo) throws Exception {
        JwtBuilder builder = Jwts.builder()
                .setSubject(jwtInfo.getUniqueName())
                .claim(UserInfoConstant.USER_ID, jwtInfo.getId())
                .claim(UserInfoConstant.USER_NAME, jwtInfo.getName())
                .claim(UserInfoConstant.USER_TYPE, otherInfo.get(UserInfoConstant.USER_TYPE))
                .claim(UserInfoConstant.EXPIRE, expire.getTime());
        if (null != otherInfo) {
            for (Map.Entry<String, String> entry : otherInfo.entrySet()) {
                builder.claim(entry.getKey(), entry.getValue());
            }
        }
        return builder.signWith(SignatureAlgorithm.RS256, RsaKeyHelper.getPrivateKey(priKey)).compact();
    }

    /***
     * 功能说明：公钥解析token
     *
     * @author 王大宸
     * @date 2020/7/8 9:46
     * @param token
     * @param pubKey
     * @return Jws<Claims>
     */
    public Jws<Claims> parserToken(String token, byte[] pubKey) throws Exception {
        return Jwts.parser().setSigningKey(RsaKeyHelper.getPublicKey(pubKey)).parseClaimsJws(token);
    }

    /***
     * 功能说明：获取token中的用户信息
     *
     * @author 王大宸
     * @date 2020/7/8 9:46
     * @param token
     * @param pubKey
     * @return com.ssgm.common.auth.jwt.IJWTInfo
     */
    public IJWTInfo getInfoFromToken(String token, byte[] pubKey) throws Exception {
        Jws<Claims> claimsJws = parserToken(token, pubKey);
        Claims body = claimsJws.getBody();
        Map<String, String> otherInfo = new HashMap<String, String>();
        for (Map.Entry<String, Object> entry : body.entrySet()) {
            if (Claims.SUBJECT.equals(entry.getKey())
                    || UserInfoConstant.USER_ID.equals(entry.getKey())
                    || UserInfoConstant.USER_NAME.equals(entry.getKey())
                    || UserInfoConstant.EXPIRE.equals(entry.getKey())) {
                continue;
            }
            otherInfo.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
        }
        return new JWTInfo(body.getSubject(),
                StringHelper.getObjectValue(body.get(UserInfoConstant.USER_ID)),
                StringHelper.getObjectValue(body.get(UserInfoConstant.USER_NAME)),
                new DateTime(body.get(UserInfoConstant.EXPIRE)).toDate(),
                otherInfo);
    }

}
